using UnityEngine;
using System.Collections;

namespace MenuItems
{
	/// <summary>
	/// Options active event.
	/// </summary>
	public delegate void OptionsActiveEvent (bool active);


	/// <summary>
	/// Options.
	/// </summary>
	public class Options : MonoBehaviour
	{
		//Unity inspector Variables
		public GUISkin skinForGUI;

		public GUIStyle OkButtonStyle;
		public GUIStyle ApplyButtonStyle;
		public GUIStyle BackButtonStyle;

		//Option Menu's events
		public event OptionsActiveEvent OptionsStateChange;

		//Class Variables
		private static Options m_Instance;
		private float buttonPosition;
		private bool visible;
		private Rect windowRect; 

		//TODO: Screen res change timeout
		//private int countdown; 
		
		//Volume Variables
		private float masterVolume;
		private float musicVolume;
		private float sfxVolume;
		private bool masterMute;
		private bool musicMute;
		private bool sfxMute;

		//Resolution Variables
		private Resolution[] resolutionList;
		private GUIContent[] GUIConList;
		private Resolution currentResoultion;
		private bool fullscreen;
		private bool resList;
		private string refreshRate;
		private int resolutionID;
		//Gameplay Variables
		//TODO: Game related Settings
		
		public void Awake ()
		{
			m_Instance = this;
			visible = false;
			//countdown = 0;
			buttonPosition = Screen.height - Screen.height * 0.222f;
			int windowWidth = skinForGUI.window.active.background.width;
			int windowHeight = skinForGUI.window.active.background.height;
			windowRect = new Rect (Screen.width / 2 - windowWidth / 2, buttonPosition - windowHeight - 100, windowWidth, windowHeight);

			//Get resloutions
			fullscreen = Screen.fullScreen;
			currentResoultion = Screen.currentResolution;
			resolutionID = -1;
			resolutionList = Screen.resolutions;
			refreshRate = Screen.currentResolution.refreshRate.ToString ();
			resList = false;

			//Populate GUI list for resolutions
			System.Array.Reverse (resolutionList);
			GUIConList = new GUIContent[resolutionList.Length];
			int count = 0;
			foreach (Resolution element in resolutionList) {
				GUIConList [count] = new GUIContent (NiceRes (element));
				count++;
			}

			//TODO: file save and loading
			//Volume controls 0 - 10
			masterVolume = 10.0f;
			musicVolume = 10.0f;
			sfxVolume = 10.0f;
			masterMute = !System.Convert.ToBoolean (masterVolume);
			musicMute = !System.Convert.ToBoolean (musicVolume);
			sfxMute = !System.Convert.ToBoolean (sfxVolume);
		}
		
		void OnDisable ()
		{
			m_Instance = null;
		}

		/// <summary>
		/// Closes the options.
		/// </summary>
		private void closeOptions ()
		{
			Visible = false;
		}

		/// <summary>
		/// Applies the options.
		/// </summary>
		/// <returns><c>true</c>, if options was applyed, <c>false</c> otherwise.</returns>
		private bool applyOptions ()
		{
			//TODO: Save settings and apply
			//Use playerprefs
			return true;
		}

		/// <summary>
		/// Accepts the options.
		/// </summary>
		private void acceptOptions ()
		{
			if (applyOptions ()) {
				closeOptions ();
			}
		}
		
		// Update is called once per frame
		public void Update ()
		{
			
		}

		public void OnGUI ()
		{
			if (visible) {
				GUI.skin = skinForGUI;
				GUI.Window (0, windowRect, windowContents, "");
				if (GUI.Button (new Rect (Screen.width / 2 - 150, buttonPosition, 100, 32), "", OkButtonStyle)) {
					acceptOptions ();
				}
				if (GUI.Button (new Rect (Screen.width / 2 - 50, buttonPosition, 100, 32), "", ApplyButtonStyle)) {
					applyOptions ();
				}
				if (GUI.Button (new Rect (Screen.width / 2 + 49, buttonPosition, 100, 32), "", BackButtonStyle)) {
					closeOptions ();
				}
			}
		}

		/// <summary>
		/// Mutes the sound.
		/// </summary>
		/// <param name="position">Position.</param>
		/// <param name="sliderValue">Slider value.</param>
		/// <param name="toggle">Toggle.</param>
		private void SoundMute (Rect position, ref float sliderValue, ref bool toggle)
		{
			//If mute gets pressed change the slider
			//only if it is not already set.
			toggle = GUI.Toggle (position, toggle, "Mute");
			if (toggle && sliderValue != 0.0f) {
				sliderValue = 0.0f;
			} else if (!toggle && sliderValue == 0.0f) {
				sliderValue = 10.0f;
			}
		}

		/// <summary>
		/// Updates the slider.
		/// </summary>
		/// <param name="position">Position.</param>
		/// <param name="sliderValue">Slider value.</param>
		/// <param name="muteToggle">Mute toggle.</param>
		private void updateSlider (Rect position, ref float sliderValue, ref bool muteToggle)
		{
			//Make sure to toggle the mute 
			//when moving the slider 
			sliderValue = GUI.HorizontalSlider (position, sliderValue, 0.0F, 10.0F);
			if (sliderValue == 0.0f && !muteToggle) {
				muteToggle = true;
			} else if (sliderValue > 0.0f && muteToggle) {
				muteToggle = false;
			}
		}

		/// <summary>
		/// Contains the contents of the window.
		/// </summary>
		/// <param name="WindowID">Window I.</param>
		private void windowContents (int WindowID)
		{
			//FullScreen 
			string fullscreenIndicator = "";
			if (fullscreen) {
				fullscreenIndicator = "ON";
			} else {
				fullscreenIndicator = "OFF";
			}
			fullscreen = GUI.Toggle (new Rect (windowRect.width - 120, 115, 100, 32), fullscreen, fullscreenIndicator);

			//Resolution List
			resList = GUI.Toggle (new Rect (windowRect.width - 120, 146, 100, 32), resList, NiceRes (currentResoultion));

			//If the list is shown remove the other buttons in the else
			if (resList) {
				Rect dropdownRect = new Rect (windowRect.width - 120, 177, 100, 32 * resolutionList.Length);
				GUI.Box (dropdownRect, "");
				int select = GUI.SelectionGrid (dropdownRect, -1, GUIConList, 1);

				//If something was clicked in SelectionGrid select it & close
				if (select != -1) {
					resList = false;
					resolutionID = select;
					currentResoultion = resolutionList [select];
				}
			} else {
				//Refresh Rate
				refreshRate = GUI.TextField (new Rect (windowRect.width - 120, 177, 100, 32), refreshRate);


				//Sound options
				SoundMute (new Rect (windowRect.width - 120, 253, 100, 32), ref masterVolume, ref masterMute);
				SoundMute (new Rect (windowRect.width - 120, 284, 100, 32), ref musicVolume, ref musicMute);
				SoundMute (new Rect (windowRect.width - 120, 315, 100, 32), ref sfxVolume, ref sfxMute);

				
				//Gameplay Options

			}
			//Slider controls
			updateSlider (new Rect (windowRect.width / 2 - 30, 265, 150, 30), ref masterVolume, ref masterMute);
			updateSlider (new Rect (windowRect.width / 2 - 30, 296, 150, 30), ref musicVolume, ref musicMute);
			updateSlider (new Rect (windowRect.width / 2 - 30, 327, 150, 30), ref sfxVolume, ref sfxMute);
		}

		/// <summary>
		/// Converts the resolution to a nicer looking string.
		/// </summary>
		/// <returns>The res.</returns>
		/// <param name="res">Res.</param>
		private string NiceRes (Resolution res)
		{
			return (res.width.ToString () + " x " + res.height.ToString ());
		}

		/// <summary>
		/// Gets or sets a value indicating whether this <see cref="MenuItems.Options"/> is visible.
		/// </summary>
		/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
		public bool Visible {
			get {
				return visible;
			}
			set {
				//Setup Event handle on enable/disable of options
				if (OptionsStateChange != null) {
					//if not null send callback to all listeners
					OptionsStateChange (value);
				}
				this.visible = value;
			}
		}

		/// <summary>
		/// Gets or sets the master volume.
		/// </summary>
		/// <value>The master volume.</value>
		public float MasterVolume {
			get {
				return masterVolume;
			}
			set {
				masterVolume = value;
			}
		}

		/// <summary>
		/// Gets or sets the music volume.
		/// </summary>
		/// <value>The music volume.</value>
		public float MusicVolume {
			get {
				return musicVolume;
			}
			set {
				musicVolume = value;
			}
		}

		/// <summary>
		/// Gets or sets the sfx volume.
		/// </summary>
		/// <value>The sfx volume.</value>
		public float SfxVolume {
			get {
				return sfxVolume;
			}
			set {
				sfxVolume = value;
			}
		}

		/// <summary>
		/// Gets the options instance.
		/// </summary>
		/// <value>The instance.</value>
		public static Options Instance {
			get {
				if (m_Instance == null) {
					Debug.LogError ("Options: No instance of Options is found, attatch to object first.");
				}
				return m_Instance; 
			} 
		}
	}
}